package reflect

import (
	"reflect"
)

// 反射给指定某个对象的字段设置值 包括在他的父类
func SetFieldValue(obj any, fieldName string, value any) bool {
	wr := reflect.ValueOf(obj)
	wrt := reflect.TypeOf(obj)

	fieldLinekd := make([]string, 0)
	hasField := IsFieldTypeContain(wrt, fieldName, &fieldLinekd)
	if !hasField {
		return false
	}

	for i := 0; i < len(fieldLinekd); i++ {
		fname := fieldLinekd[i]
		for j := 0; j < wr.Elem().NumField(); j++ {
			f := wrt.Elem().Field(j)
			if f.Name == fname {
				wr = wr.Elem().Field(j)
				wrt = wrt.Elem().Field(j).Type
			}
		}
	}

	// for i := 0; i < wr.Elem().NumField(); i++ {
	// 	f := wrt.Elem().Field(i)
	// 	fname := f.Name
	// 	ftype := f.Type
	// 	if fname == fieldName {
	// 		if ftype.Kind() == reflect.Ptr {
	// 			wr.Elem().Field(i).Set(reflect.ValueOf(value))
	// 		}
	// 		return true
	// 	} else {
	// 		if ftype.Kind() == reflect.Struct || ftype.Kind() == reflect.Ptr {
	// 			fmt.Println(wr.Elem(), "|---")
	// 			contain := SetFieldValue(wr.Elem().Field(i).Interface(), fieldName, value)
	// 			if contain {
	// 				return true
	// 			} else {

	// 			}
	// 		}
	// 	}
	// 	fmt.Printf("%+v\n", reflect.New(wrt.Elem().Field(i).Type.Elem()))
	// }
	//reflect.ValueOf(work).Elem().FieldByName("ProtobufNetWork").Set(pr)
	return true
}

func Test(obj any, fieldLinked *[]string, index int, value any) {
	if index < 0 {
		return
	}
	fieldName := (*fieldLinked)[index]
	wr := reflect.ValueOf(obj)
	wrt := reflect.TypeOf(obj)
	vfield := wr.FieldByName(fieldName)
	tfield, _ := wrt.FieldByName(fieldName)
	println(tfield.Type)
	if tfield.Type.Kind() == reflect.Ptr {
		if vfield.IsNil() {

			// fmt.Println(vfield.Elem())
			// fmt.Println(vfield.Type())
			// val := reflect.New(vfield.Type())
			// fmt.Printf("%#v\n", val)
			//vfield.Set(reflect.New(vfield.Elem().Type()))
		}
	}
	Test(vfield.Interface(), fieldLinked, index-1, value)
}

// 判断指定字段名称是否存在与某个类型中
// @param t 要查询的类型
// @param fieldName 要查询的字段名称
// @param fieldLinked 返回字段链
func IsFieldTypeContain(t reflect.Type, fieldName string, fieldLinked *[]string) bool {
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		fname := f.Name
		ftype := f.Type
		if fname == fieldName {
			*fieldLinked = append(*fieldLinked, fname)
			return true
		} else {
			if ftype.Kind() == reflect.Struct || ftype.Kind() == reflect.Ptr {
				if ftype.Kind() == reflect.Ptr {
					ftype = ftype.Elem()
				}
				if IsFieldTypeContain(ftype, fieldName, fieldLinked) {
					*fieldLinked = append(*fieldLinked, fname)
					return true
				}
			}
		}
	}
	return false
}
